vim9script noclear

# Vim global plugin for qbs=>
# Last Change:	2024-02-02
# Maintainer:	jcodelong <jcodelong@qq.com>

# License:	This file is placed in the public domain.


#######################################################################################
#
#    注意：只有在qbs安装目录下的文件才有效。目前遵循的原则是qbs只会去读写qbs目录下的文件
#
#                 1. make sure the communication channel is open
#          <F8> : 2. choose one item in canvas
#                 3. press <F8> in gvim, 
#
#          <F11>: 向上搜索 （%%    %%）， 并发送到qbs, 从而实现跳转到流程图      
#
#          <F12>: 向下搜索 （%%    %%）， 并发送到qbs, 从而实现跳转到流程图
#  
#
#######################################################################################


#确保这个插件只会加载一次
if exists("g:loaded_qbs")
	finish
endif
g:loaded_qbs = 1

var count = 4

###g:mapleader = "_"
###the mapping will define "_a".  If the user didn't do this, the default value will be used, which is a backslash.  Then a map for "\a" will be defined.


	if !hasmapto('<Plug>Qbs;')
	  map <unique> <Leader>a  <Plug>Qbs;
	endif



### This checks if a mapping to "<Plug>TypecorrAdd;" already exists, and only defines the mapping from "<Leader>a" if it doesn't.  The user then has a chance of putting this in their vimrc file: 

###	map ,c  <Plug>TypecorrAdd;

### Then the mapped key sequence will be ",c" instead of "_a" or "\a".

	noremap <unique> <script> <Plug>Qbs;  <SID>Qbs_test
#	noremenu <script> Plugin.Qbs_test\ Test      <SID>Qbs_test
	noremap <SID>Qbs_test  :call <SID>Qbs_test()<CR>


	def Add(from: string, correct: bool)
	  var to = input($"type the correction for {from}: ")
	  exe $":iabbrev {from} {to}"
	  if correct | exe "normal viws\<C-R>\" \b\e" | endif
	  count += 1
	  echo "you now have " .. count .. " corrections"
	enddef

	if !exists(":Correct")
	  command -nargs=1  Correct  call Add(<q-args>, false)
	endif

# 这是文件类型，
#(defconst FILE-TYPE--UNKNOWN 0 "---")
#(defconst FILE-TYPE--C-SERIES 1 "---")
#(defconst FILE-TYPE--SHELL 2 "---")
#(defconst FILE-TYPE--ELISP 3 "---")
#(defconst FILE-TYPE--PYTHON 4 "---")


g:part1 =  "<cmd-end/>\n
\<cmd-start/>\n
\\n
\<set-target-canvas>\n
\<canvas-filename>CURRENT-CANVAS</canvas-filename>\n
\</set-target-canvas>\n
\<网络文件独占模式>\n
\ <action--drop-package \n
\		       parent-uid = \"FIRST-CHOOSED\" \n
\                       x=\"500\" y =\"400\"  \n
\		       XY-确定方法 = \"FIRST-CHOOSED > RIGHT-TOP > 0 > 0\"\n
\                       flags = \"x-y-is-canvas-coordinate\"\n
\                       filename=\"./package/000/pkg/src-location.better.pkg\" start-pos=\"48\" \n
\                       />\n
\<sequence-operation-on-package>\n
\     <package-uid>CREATED-JUST-NOW</package-uid> \n
\ \n
\<port-index> 4  </port-index>   <port-value>"

g:part2 = "</port-value> <port-index> 5  </port-index>   <port-value>"
g:part3 = "</port-value>"
g:part4 = "<package-uid>FIRST-CHOOSED</package-uid>\n
\<get-package-or-jci-include-self/>\n
\<发送canvas定位xml命令>\n
\      <文件类型>"
  
g:part5 = "</文件类型>"
g:part6 = "</发送canvas定位xml命令>\n
\</sequence-operation-on-package >\n
\</网络文件独占模式>\n
\<cmd-end/>   "

g:part_a = "["
g:part_b = "]"


#===============================================
#
def Set_const_string_according_file_type(filetype: number)
    if (filetype == 0)
       g:part_a = "["
       g:part_b = "]"
    elseif (filetype == 1)
       g:part_a = "//["
       g:part_b = "]"
    elseif (filetype == 2)
       g:part_a = "#["
       g:part_b = "]"
    elseif (filetype == 3)   
       g:part_a = ";["
       g:part_b = "]"
    elseif (filetype == 4)   
       g:part_a = "#["
       g:part_b = "]"
    endif
enddef




#===============================================
#这个没有调通，没有使用
def RandomString(n: number)
  #var ret:string
  var ret = ""
  for i in range(a:n)
    let j = rand()
    let c = nr2char(char2nr('a') + (j % 26))
    let ret .= c
  endfor
  return ret
enddef

#===============================================
	func Qbs_Handle(channel, msg)
	  echo 'Received: ' .. a:msg
	  execute 'normal! i' .. a:msg
	endfunc


 g:channel = ch_open("127.0.0.1:27193", {"mode": "raw", "callback": "Qbs_Handle"})
 g:cmd_max_len = 2048

 g:relative_path_1 =  "/home/guest/qbs/"
 g:relative_path_2 =  "~/guest/qbs/"

 g:tt132 = system('echo -n $QBS_INSTALL_PATH_1')
 if (strlen(g:tt132) > 1)
    g:relative_path_1 = g:tt132
 endif
 g:tt111 = system('echo -n $QBS_INSTALL_PATH_2')
 if (strlen(g:tt111) > 1)
    g:relative_path_2 = g:tt111
 endif

 g:relative_path_1_len = strlen(g:relative_path_1)
 g:relative_path_2_len = strlen(g:relative_path_2)

 #echo g:relative_path_1
 #echo g:relative_path_1_len
 #echo g:relative_path_2
 #echo g:relative_path_2_len

#/mnt/nvme0n1p5/jsx/qt3/auto/gtk-c/src/tree-to-tre1.sh 
#===============================================
	def Qbs_test()
	    #1 打印信息，说明这个函数得到执行了
	    echo "Qbs_test() ok"
	    echo bufname("%")
	    var bf: string
	    var filename: string
	    bf = bufname("%")
	    #err
	    #filename = ${bf##*/}
	    #ok, but ../../name.txt => ../../name
	    #filename = expand("%:r")
	    #ok, ../../name.txt => name.txt
	    #2 取得当前buffer的文件名（包括后缀）和后缀名
	    filename = expand("%:t")
	    var ext: string
	    ext =  expand("%:e")

	    echo filename
	    echo ext
	    #3 根据后缀名确定文件类型
	    var filetype: number
	    	filetype = 0
	    if (ext == 'c') 
	       filetype = 1   
	    elseif (ext == 'c++')
	    	   filetype = 1	
            elseif (ext == 'cpp')
	    	   filetype = 1	
            elseif (ext == 'h')
	    	   filetype = 1	
            elseif (ext == 'hpp')
	    	   filetype = 1	
	    	elseif (ext == 'ts')
	    	   filetype = 1	
            elseif (ext == 'json')
	    	   filetype = 1	
	    endif	    
	    #,(ext == 'c++'),(ext == 'cpp'),(ext == 'h'),(ext == 'hpp'))
	    if (ext == 'sh') || (ext == 'vim')
	       filetype = 2
	    elseif (ext == 'el')
	    	   filetype = 3
	    elseif (ext == 'py')
	    	   filetype = 4			   
	    endif   
	    #3.1 根据文件类型设置前缀，
	    Set_const_string_according_file_type(filetype)	

	    #4 debug打印一些固定的全局变量
	    if (0)
	      echo filetype
	      echo g:part1
	      echo g:part2
	      echo g:part3	    
	      echo g:part4
	      echo g:part5
	      echo g:part6

	      echo g:part_a
	      echo g:part_b
	    endif
	    
	    if filetype == 0
	    
	    else

	    endif

	    #echo RandomString(20)
	    #execute 'tr -dc A-Za-z0-9 </dev/urandom | head -c 20; echo'
	    #5 生成一个20字符长度的随机字符串
	    #var randstr = system('tr -dc A-Za-z0-9 </dev/urandom | head -c 20; echo') #这个末尾有一个回车键，不合要求
	    var randstr = system('tr -dc A-Za-z0-9 </dev/urandom | head -c 20') 
	    echo "randstr is "
	    echo randstr
   #6 检查需要打开的网络连接，如果没打开，重新打开	    
   if ch_status(g:channel) == "open"
      echo "channel is open already"
   else
      g:channel = ch_open("127.0.0.1:27193", {"mode": "raw", "callback": "Qbs_Handle"})
      echo "channel is not ready,  try to open it here..."
   endif

   #7 这里，网络连接应该是打开的，如果不是，就是错误了，什么也不用做了
   if ch_status(g:channel) == "open"
      echo "channel is open, do something..."
      var write_to_buffer1 = g:part_a .. randstr .. g:part_b
      echo write_to_buffer1

      #execute ':i' .. ' ' .. write_to_buffer1 
      execute 'normal! o' .. write_to_buffer1
      #var cmd1 = 'o ' .. write_to_buffer1 .. '<Esc>'
      #normal cmd1
      #normal oabsdc<Esc>

      execute 'normal! a ' .. " (%%" .. " %%)"
      execute 'normal! hhh'
      #normal hhh      

      var fullpath_filename = expand("%:p")  
      echo fullpath_filename
      #execute 'normal! a ' ..	fullpath_filename

      ## both line are ok, just debug
      #echo match(fullpath_filename, "/mnt/nvme0n1p5")	
      #echo match(fullpath_filename, g:relative_path_2)

      var m1 = match(fullpath_filename, g:relative_path_1)
      var relative_path_filename: string
      echo m1
      if (m1 == 0 )
      	 relative_path_filename = "./" .. strpart(g:relative_path_1, g:relative_path_1_len, -1) 
      else
      endif

      var m2: number
      m2 = -1
      if (m1 == 0 )
      else
	echo "wwwwwwwww" .. fullpath_filename .. g:relative_path_2
	m2 =  match(fullpath_filename, g:relative_path_2)
	echo m2
	echo "eeeeeeee"
	if (m2 == 0 )
	   echo g:relative_path_2_len
      	   relative_path_filename = "./" .. strpart(fullpath_filename, g:relative_path_2_len)
	   echo "relative_path_filename is ok "
      	else
      	endif
      endif
      echo "relative_path_filename is ok-------- "
      if (m1 == 0) || (m2 == 0)
         #execute 'normal! a ' ..	relative_path_filename
	 echo "relative_path_filename is ok "
	 echo relative_path_filename
         var output_to_qbs =  g:part1 .. randstr .. g:part2 .. relative_path_filename  ..  g:part3 .. g:part4 .. "c or cpp" ..  g:part5 .. g:part6

	 ch_sendraw(g:channel, output_to_qbs)


      else
         #这个文件不在qbs安装目录下面，do nothing
	 echo "这个文件不在qbs安装目录下面，do nothing"
      endif

      echo  "finished."
   else
	echo "open channel failed, do nothing"
   endif


	enddef

#===============================================
#
def Qbs_get_buffer_text_segment(sstart_line: number, sstart_col: number, send_line: number, send_col: number): string
    var start_line: number
    var start_col: number
    var end_line: number
    var end_col: number
    
start_line = sstart_line	 
start_col = sstart_col
end_line = send_line
end_col  = send_col

var ret: string
    ret = ""
    if (start_line <= 0)
       start_line = 1
    endif



    if (start_line > end_line)
       #do nothing
    else
       var cur_line = start_line
       var all_lines = getline(start_line, end_line)
       echo all_lines[0]
       #echo all_lines[1]
       if (start_line == end_line)
         #同一行
         ret = strpart(all_lines[0], start_col - 1, end_col - start_col + 1) 
       else
         #todo： 多行
	 var head_line = all_lines[0]  #line31
	 all_lines[0] = strpart(head_line, start_col - 1 )
	 var tail_line = all_lines[-1]
	 all_lines[-1] = strpart(tail_line, 1, end_col  )

	 var index_tmp = 0
	 for ll in all_lines
	   index_tmp = index_tmp + 1
	   if (index_tmp == 1)
	      ret = ret .. ll
	   else
	      ret = ret .. "\n" .. ll
	   endif   
	 endfor

       endif



    endif	   
    
    return ret
enddef

#===============================================
#向上搜索 （%%    %%）， 并发送到qbs, 从而实现跳转到流程图
def Qbs_jump_up()

    echo "Qbs_jump()ok"
    var line_num = line(".")	
    var col_num = col(".")

    var stop_line = line_num - 50
    if (stop_line < 0)
       stop_line = 1
    endif
    
    var search_result = search( "(%%", "bW", stop_line )
    echo search_result
    var start_pos: any
    var end_pos: any
    if (search_result > 0)
       start_pos = getpos(".")
       #line 17
       stop_line = start_pos[0] + 5  #stop_line = getpos(".")[0] + 5
       search_result = search( "%%)", "cWe", stop_line )
       if (search_result > 0)
          end_pos = getpos(".")
	  echo start_pos
	  echo end_pos

	  #调试
	  var t123 = Qbs_get_buffer_text_segment(1, 2, 3, 10)
	  echo t123
	  #得到命令
	  var cmd = Qbs_get_buffer_text_segment(start_pos[1], start_pos[2], end_pos[1], end_pos[2])	 

   #j6 检查需要打开的网络连接，如果没打开，重新打开	    
   if ch_status(g:channel) == "open"
      echo "channel is open already"
   else
      g:channel = ch_open("127.0.0.1:27193", {"mode": "raw", "callback": "Qbs_Handle"})
      echo "channel is not ready,  try to open it here..."
   endif
   
   #j7 这里，网络连接应该是打开的，如果不是，就是错误了，什么也不用做了
   if ch_status(g:channel) == "open"
	  ch_sendraw(g:channel, cmd)
   endif	  
	  #移动光标到开始
	  cursor(start_pos[1], start_pos[2])


       else
         echo "cannot find end string"
       endif

    else
        echo "cannot find start string"
    endif
    

enddef
#===============================================
#向下搜索 （%%    %%）， 并发送到qbs, 从而实现跳转到流程图
def Qbs_jump_down()

    echo "Qbs_jump()ok"
    var line_num = line(".")	
    var col_num = col(".")

    var stop_line = line_num + 50
    if (stop_line < 0)
       stop_line = 1
    endif
    
    var search_result = search( "%%)", "We", stop_line )
    echo search_result
    var start_pos: any
    var end_pos: any
    if (search_result > 0)
       start_pos = getpos(".")
       #line 17
       stop_line = start_pos[0] - 5  #stop_line = getpos(".")[0] + 5
       echo stop_line
       if (stop_line < 1)
         stop_line = 1
       endif
       search_result = search( "(%%", "bcW", stop_line )
       if (search_result > 0)
          end_pos = getpos(".")
	  echo start_pos
	  echo end_pos

	  #调试
	  var t123 = Qbs_get_buffer_text_segment(1, 2, 3, 10)
	  echo t123
	  #得到命令
	  var cmd = Qbs_get_buffer_text_segment(end_pos[1], end_pos[2], start_pos[1], start_pos[2])	 

   #j6 检查需要打开的网络连接，如果没打开，重新打开	    
   if ch_status(g:channel) == "open"
      echo "channel is open already"
   else
      g:channel = ch_open("127.0.0.1:27193", {"mode": "raw", "callback": "Qbs_Handle"})
      echo "channel is not ready,  try to open it here..."
   endif
   
   #j7 这里，网络连接应该是打开的，如果不是，就是错误了，什么也不用做了
   if ch_status(g:channel) == "open"
	  ch_sendraw(g:channel, cmd)
   endif	  
	  #移动光标到开始
	  cursor(start_pos[1], start_pos[2])


       else
         echo "cannot find end string( (%% )"
       endif

    else
        echo "cannot find start string( %%)  ) "
    endif
    

enddef
#——————————————————————TT——————————————————————
	#这里， 生成命令（TT），对应调用 call Qbs_test()
	if !exists(":qbs_test")
	  command -nargs=0  TT  :call Qbs_test()
	endif


#-------------------------------------------
	#ok
	#map <F8> iabc<Esc>
	#这里，把 <F8> 映射为命令（TT）
	#  this will diskplay echo
	#map <F8> :TT<CR>
	#  this will not see echo
	map <F8> :TT<CR><CR>


#——————————————————————JUMP_UP——————————————————————
	#这里， 生成命令（JUMP），对应调用 call Qbs_test()
	if !exists(":Qbsup")
	  command -nargs=0  Qbsup  :call Qbs_jump_up()
	endif


#-------------------------------------------
	#ok
	#map <F8> iabc<Esc>
	#这里，把 <F11> 映射为命令（Qbsup）
	#  this will diskplay echo, for debug 
	#map <F11> :Qbsup<CR>
	#  this will not see echo
	map <F11> :Qbsup<CR><CR>


#——————————————————————JUMP_DOWN——————————————————————
	#这里， 生成命令（Qbsdown），对应调用 call Qbs_test()
	if !exists(":Qbsdown")
	  command -nargs=0  Qbsdown  :call Qbs_jump_down()
	endif


#-------------------------------------------
	#ok
	#map <F8> iabc<Esc>
	#这里，把 <F12> 映射为命令（Qbsdown）
	#  this will diskplay echo , for debug 
	#map <F12> :Qbsdown<CR>
	#  this will not see echo
	map <F12> :Qbsdown<CR><CR>
